package com.fingard.dsp.bank.directbank.vbao02;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.directbank.vbao02.cust.request.BatchPayRecJSONRequest;
import com.fingard.dsp.bank.directbank.vbao02.cust.request.BatchPayRecRequest;
import com.fingard.dsp.bank.directbank.vbao02.cust.request.BatchPayRecRequestDetail;
import com.fingard.dsp.bank.directbank.vbao02.cust.request.BatchQueryRequest;
import com.fingard.dsp.bank.directbank.vbao02.util.Base64ForRSA;
import com.fingard.dsp.bank.directbank.vbao02.util.RSAUtil;
import com.fingard.dsp.bank.directbank.vbao02.util.SignUtil;
import com.fingard.dsp.bank.directbank.vbao02.util.VbaoChargePostHandler;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;

import java.net.URLEncoder;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class VBAO02BatPayRec extends VBAO02Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        return d_BatPayRec(p_req1988);
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        return d_QryBatPayRec(p_req1998);
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return d_BatPayRec(p_req9188);
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return d_QryBatPayRec(p_req9198);
    }

    public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
        retAts.reqSeqID = p_reqBat.reqBatchNO;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqBat.ownAct, "");
            if (actItem == null) {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号[" + p_reqBat.ownAct + "]商户配置信息!";
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;

                retAts.writeRetToATS();
                return retAts;
            }
            
            
			List<BatchPayRecRequestDetail> detailList = new ArrayList<BatchPayRecRequestDetail>();
			
			String signData = new String();
            while (p_reqBat.readRecord()) {
            	BatchPayRecRequestDetail batSingleDetail = new BatchPayRecRequestDetail();
            	
            	batSingleDetail.setCustBatchNo(p_reqBat.readedDetail.askNumber);
            	
            	String oppAct = "";
            	String oppName = "";
            	String oppBankCode = "";
            	if ("1988".equals(p_reqBat.reqHeader.transType)) {
            		oppAct = p_reqBat.readedDetail.recAct;
            		oppName = p_reqBat.readedDetail.recName;
            		oppBankCode = getBankConfig().getMapValueByKey("BankCodeMapping", p_reqBat.readedDetail.recBankCode);
            	} else {
            		oppAct = p_reqBat.readedDetail.payAct;
            		oppName = p_reqBat.readedDetail.payName;
            		oppBankCode = getBankConfig().getMapValueByKey("BankCodeMapping", p_reqBat.readedDetail.payBankCode);
            	}
            	
            	batSingleDetail.setOrderAmount(p_reqBat.readedDetail.payAmount);
            	
            	String isPrivate = p_reqBat.readedDetail.isPrivate;
            	if ("1".equals(isPrivate)) {
            		isPrivate = "0";
            	} else {
            		isPrivate = "1";
            	}
            	batSingleDetail.setAccType(isPrivate);
            	
            	String cardType = "0"; /* 银行卡 : 默认值 */
                if ("1".equals(p_reqBat.readedDetail.cardType)) {
                    cardType = "1"; /* 存折 */
                }
                if ("3".equals(p_reqBat.readedDetail.cardType) || "4".equals(p_reqBat.readedDetail.cardType)) {
                    cardType = "2"; /* 信用卡 */
                }
                batSingleDetail.setBankCardType(cardType);
                batSingleDetail.setBankCode(oppBankCode);
                batSingleDetail.setBankCardNo(oppAct);
                batSingleDetail.setBankCardName(oppName);
                batSingleDetail.setBankLineCode(p_reqBat.readedDetail.cnapsCode);
                batSingleDetail.setBankLineName(p_reqBat.readedDetail.cnapsName);
                batSingleDetail.setBankProvince(p_reqBat.readedDetail.getOppProvinceAndCity2()[0]);
                batSingleDetail.setBankCity(p_reqBat.readedDetail.getOppProvinceAndCity2()[1]);
                batSingleDetail.setCertType(convertCertTypeToBank(p_reqBat.readedDetail.certType));
                batSingleDetail.setCertId(p_reqBat.readedDetail.certNum);
                batSingleDetail.setMobile(p_reqBat.readedDetail.cellPhone);
                batSingleDetail.setCreditValid(p_reqBat.readedDetail.expiredDate);
                batSingleDetail.setCreditCvv2(p_reqBat.readedDetail.cvv2);
                batSingleDetail.setPurpose(p_reqBat.readedDetail.purpose);
                batSingleDetail.setMemo(p_reqBat.readedDetail.memo);
                batSingleDetail.setDescription(p_reqBat.readedDetail.abstractATS);
                
                @SuppressWarnings("unchecked")
				Map<String, Object> mapDetail = JSONObject.parseObject(JSONObject.toJSONString(batSingleDetail), Map.class);
    	        signData += SignUtil.getSignContent(mapDetail);
                detailList.add(batSingleDetail);
            }
            
            BatchPayRecJSONRequest batJSONRequest = new BatchPayRecJSONRequest();
            batJSONRequest.setDetails(signData);
            batJSONRequest.setVersion("V5.1");
            batJSONRequest.setInputCharset(getCharset());
			
			String productNo = "";
			if ("1988".equals(p_reqBat.reqHeader.transType)) {
				productNo = getBankConfig().getMapValueByKey("productNoMapping", "batPay");
        	} else {
        		productNo = getBankConfig().getMapValueByKey("productNoMapping", "batRec");
        	}
			batJSONRequest.setProductNo(productNo);
			batJSONRequest.setCustBatchSeq(p_reqBat.reqBatchNO);
			batJSONRequest.setTotalNum(p_reqBat.totalNum);
			batJSONRequest.setTotalPrice(p_reqBat.totalAmt);
			
			String  json = JSONObject.toJSONString(batJSONRequest);
	        @SuppressWarnings("unchecked")
			Map<String, Object> mapJson = JSONObject.parseObject(json, Map.class);
	        String signSend = SignUtil.getSignContent(mapJson);
	        WriteBankLogLn2("待签名请求数据:\r\n" + signSend);
	        String sign = SignUtil.getDigest(signSend + actItem.saltKey);
            
            BatchPayRecRequest batRequest = new BatchPayRecRequest();
            batRequest.setDetails(detailList);
			batRequest.setVersion("V5.1");
			batRequest.setInputCharset(getCharset());
			batRequest.setProductNo(productNo);
			batRequest.setCustBatchSeq(p_reqBat.reqBatchNO);
			batRequest.setTotalNum(p_reqBat.totalNum);
			batRequest.setTotalPrice(p_reqBat.totalAmt);

			String  reqMsg = JSONObject.toJSONString(batRequest);
	        @SuppressWarnings("unchecked")
	        Map<String, Object> mapSend = JSONObject.parseObject(reqMsg, Map.class);
	        mapSend.put("sign", sign);
	        // 1、带MD5签名的JSON明文
	        reqMsg = JSONObject.toJSONString(mapSend);
	        WriteBankLogLn2("发送微保明文(带MD5签名):\r\n" + reqMsg);
	        
	        PublicKey publicKey = RSAUtil.getRSAPublicKeyByFileSuffix(actItem.oppCertFilePath, "pem", "RSA");
	        byte[] encryBytes = RSAUtil.encrypt(reqMsg.getBytes(getCharset()), publicKey, 2048, 11, "RSA/ECB/PKCS1Padding");
	        // 2、密文
	        reqMsg = URLEncoder.encode(new String(Base64ForRSA.encode(encryBytes).getBytes(), getCharset()), getCharset());
	        WriteBankLogLn2("发送微保密文:\r\n" + reqMsg);
	        
	        String url = bankFront.getUrl("batRecPay");
	        WriteBankUrlLogLn(url);
	        
	        VbaoChargePostHandler vbaoChargeSystemHandler = new VbaoChargePostHandler();
			String responseMsg = vbaoChargeSystemHandler.http(url, reqMsg, actItem.merchantId, bankFront.org);
	        WriteBankLogLn2("结果密文:\r\n" + responseMsg);
            
	        if (null != responseMsg && !responseMsg.equals("")) {
	            @SuppressWarnings("unchecked")
				Map<String, Object> map = JSONObject.parseObject(responseMsg, Map.class);
	            retAts.respCode = "0";
	            
	            if ("RSA".equals(map.get("encryptType"))) {
	                // 应答报文解密
	                PrivateKey privateKey = RSAUtil.getRSAPrivateKeyByFileSuffix(actItem.ownKeyStorePath, "pem", null, "RSA");
	                byte[] decodeBase64KeyBytes2 = Base64ForRSA.decode((String)map.get("reqmsg"));
	                String decodeStr = new String(RSAUtil.decrypt(decodeBase64KeyBytes2, privateKey, 2048, 11, "RSA/ECB/PKCS1Padding"), getCharset());
	                WriteBankLogLn2("解密明文JSON:\r\n" + decodeStr);
	                
	                // 应答报文签名验证
	                @SuppressWarnings("unchecked")
					Map<String, Object> resMap = JSONObject.parseObject(decodeStr, Map.class);
					
                    retAts.respInfo = (String) resMap.get("returnMessage");
                    retAts.transState = "H+" + (String) resMap.get("batchPaySts");
                    retAts.payInfoCode = (String) resMap.get("returnCode");
	            } else {
	                JSONObject resJson = JSONObject.parseObject((String) map.get("reqmsg"));
	                retAts.respInfo = resJson.getString("returnMessage");
	                retAts.transState = "H+" + resJson.getString("batchPaySts");
	                retAts.payInfoCode = resJson.getString("returnCode");
	            }
	        }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.toString();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }
    
    public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
        retAts.reqSeqID = p_reqQryBat.reqBatchNO;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_reqQryBat.ownAct, "");
            if (actItem == null) {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_reqQryBat.ownAct + "]商户配置信息";
                retAts.writeAfterDetail();
                return retAts;
            }

            BatchQueryRequest batQueryRequest = new BatchQueryRequest();
            
            batQueryRequest.setVersion("V5.1");
            batQueryRequest.setInputCharset(getCharset());
            String productNo = "";
            if ("1998".equals(p_reqQryBat.reqHeader.transType)) {
            	productNo = getBankConfig().getMapValueByKey("productNoMapping", "batPay");
            } else {
            	productNo = getBankConfig().getMapValueByKey("productNoMapping", "batRec");
            }
            batQueryRequest.setProductNo(productNo);
            batQueryRequest.setCustBatchSeq(p_reqQryBat.reqBatchNO);
            
            String  reqMsg = JSONObject.toJSONString(batQueryRequest);
	        @SuppressWarnings("unchecked")
			Map<String, Object> mapSend = JSONObject.parseObject(reqMsg, Map.class);
	        String signSend = SignUtil.getSignContent(mapSend);
	        WriteBankLogLn2("待签名请求数据:\r\n" + signSend);
	        String sign = SignUtil.getDigest(signSend + actItem.saltKey);
	        mapSend.put("sign", sign);
	        // 1、带MD5签名的JSON明文
	        reqMsg = JSONObject.toJSONString(mapSend);
	        WriteBankLogLn2("发送微保明文(带MD5签名):\r\n" + reqMsg);
	        
            PublicKey publicKey = RSAUtil.getRSAPublicKeyByFileSuffix(actItem.oppCertFilePath, "pem", "RSA");
            byte[] encryBytes = RSAUtil.encrypt(reqMsg.getBytes(getCharset()), publicKey, 2048, 11, "RSA/ECB/PKCS1Padding");
            // 2、密文
            reqMsg = URLEncoder.encode(new String(Base64ForRSA.encode(encryBytes).getBytes(), getCharset()), getCharset());
            WriteBankLogLn2("发送微保密文:\r\n" + reqMsg);
            
            String url = bankFront.getUrl("batRecPayQry");
            WriteBankUrlLogLn(url);
            
            VbaoChargePostHandler vbaoChargeSystemHandler = new VbaoChargePostHandler();
    		String responseMsg = vbaoChargeSystemHandler.http(url, reqMsg, actItem.merchantId, bankFront.org);
	        WriteBankLogLn2("结果密文:\r\n" + responseMsg);
            
	        if (null != responseMsg && !responseMsg.equals("")) {
	            @SuppressWarnings("unchecked")
				Map<String, Object> map = JSONObject.parseObject(responseMsg, Map.class);
	            if (map.get("encryptType").equals("RSA")) {
	                // 应答报文解密
	                PrivateKey privateKey = RSAUtil.getRSAPrivateKeyByFileSuffix(actItem.ownKeyStorePath, "pem", null, "RSA");
	                byte[] decodeBase64KeyBytes2 = Base64ForRSA.decode((String)map.get("reqmsg"));
	                String decodeStr = new String(RSAUtil.decrypt(decodeBase64KeyBytes2, privateKey, 2048, 11, "RSA/ECB/PKCS1Padding"),getCharset());
	                WriteBankLogLn2("解密明文JSON:\r\n" + decodeStr);
	                JSONObject respJson = JSONObject.parseObject(decodeStr);
	                
	                retAts.respCode = "0";
	                String batchStatus = (String) respJson.get("batchPaySts");
	                if ("3".equals(batchStatus)) {
	                	JSONArray tmpBatRespList = JSONArray.parseArray(respJson.getString("details"));
	                	
	                	for(int i = 0; i < tmpBatRespList.size(); i++){
			        		JSONObject tmpEachDetail = tmpBatRespList.getJSONObject(i); 
	                		
	                		RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                            if ("1998".equals(p_reqQryBat.reqHeader.transType)) {
                                tmpRetDetail.recAct = tmpEachDetail.getString("bankCardNo");
                                tmpRetDetail.recName = tmpEachDetail.getString("bankCardName");
                            } else {
                                tmpRetDetail.payAct = tmpEachDetail.getString("bankCardNo");
                                tmpRetDetail.payName = tmpEachDetail.getString("bankCardName");
                            }

                            tmpRetDetail.postScript = tmpEachDetail.getString("custBatchNo");
                            tmpRetDetail.payAmount = tmpEachDetail.getString("orderAmount");
                            tmpRetDetail.result =  "H+" + batchStatus + "+D+" + tmpEachDetail.getString("payStatus");
                            tmpRetDetail.payInfoCode = tmpEachDetail.getString("returnCode");
                            tmpRetDetail.memo = tmpEachDetail.getString("returnMessage");

                            retAts.writeRetDetail(tmpRetDetail);
			        	}
	                } else {
	                	retAts.transState = "H+" + (String) respJson.get("batchPaySts");
                        retAts.payInfoCode = (String) respJson.get("returnCode");
                        retAts.respInfo = (String) respJson.get("returnMsg");
	                }
	            } else {
	                JSONObject resJson = JSONObject.parseObject((String) map.get("reqmsg"));
	                retAts.respCode = "-1";
                    retAts.respInfo = resJson.getString("returnMsg");
	            }
	        }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}
